/*
 *
 * NDbUnit
 * Copyright (C)2005 - 2011
 * http://code.google.com/p/ndbunit
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

using System.Data;
using System.Data.Common;
using System.Text;

namespace NDbUnit.Core.MySqlClient {
#pragma warning disable 1591

	public class MySqlDbCommandBuilder : DbCommandBuilder {
		private System.Data.Common.DbProviderFactory m_factory = MySql.Data.MySqlClient.MySqlClientFactory.Instance;

		public MySqlDbCommandBuilder(IDbConnection connection)
			: base(connection) {
		}

		public MySqlDbCommandBuilder(string connectionString)
			: base(connectionString) {
		}

		public override string QuotePrefix {
			get { return "`"; }
		}

		public override string QuoteSuffix {
			get { return "`"; }
		}

		protected override IDbCommand CreateDbCommand() {

			var command = m_factory.CreateCommand();
			if (CommandTimeOutSeconds != 0)
				command.CommandTimeout = CommandTimeOutSeconds;
			return command;

		}

		protected override IDbCommand CreateInsertCommand(IDbCommand selectCommand, string tableName) {
			int count = 1;
			bool notFirstColumn = false;
			StringBuilder sb = new StringBuilder();
			sb.Append("INSERT INTO " + TableNameHelper.FormatTableName(tableName, QuotePrefix, QuoteSuffix) + "(");
			StringBuilder sbParam = new StringBuilder();
			IDataParameter sqlParameter;
			IDbCommand sqlInsertCommand = CreateDbCommand();
			foreach (DataRow dataRow in _dataTableSchema.Rows) {
				if (ColumnOKToInclude(dataRow)) {
					if (notFirstColumn) {
						sb.Append(", ");
						sbParam.Append(", ");
					}

					notFirstColumn = true;

					sb.Append(QuotePrefix + dataRow["ColumnName"] + QuoteSuffix);
					sbParam.Append(GetParameterDesignator(count));

					sqlParameter = CreateNewSqlParameter(count, dataRow);
					sqlInsertCommand.Parameters.Add(sqlParameter);

					++count;
				}

			}

			sb.Append(") VALUES(" + sbParam + ")");

			sqlInsertCommand.CommandText = sb.ToString();

			return sqlInsertCommand;
		}

		protected DbType ConvertTypeToDbType(System.Type type) 
		{
			if (type == typeof(string))
				return DbType.String;
			else if (type == typeof(int))
				return DbType.Int32;
			else if (type == typeof(long))
				return DbType.Int64;
			else if (type == typeof(short))
				return DbType.Int16;
			else if (type == typeof(uint))
				return DbType.UInt32;
			else if (type == typeof(ulong))
				return DbType.UInt64;
			else if (type == typeof(ushort))
				return DbType.UInt16;
			else if (type == typeof(byte))
				return DbType.Byte;
			else if (type == typeof(sbyte))
				return DbType.SByte;
			else if (type == typeof(bool))
				return DbType.Boolean;
			else if (type == typeof(System.DateTime))
				return DbType.DateTime;
			else if (type == typeof(decimal))
				return DbType.Decimal;
			else if (type == typeof(float))
				return DbType.Single;
			else if (type == typeof(double))
				return DbType.Double;
			else if (type == typeof(System.DateTimeOffset))
				return DbType.DateTimeOffset;
			else if (type == typeof(byte[]))
				return DbType.Binary;
			else
				return DbType.String;
		}

		protected override IDataParameter CreateNewSqlParameter(int index, DataRow dataRow)
        {
			var parameter = m_factory.CreateParameter();
			parameter.ParameterName = "?p" + index;
			parameter.DbType = ConvertTypeToDbType((System.Type)dataRow["DataType"]);// (DbType)dataRow["ProviderType"];
			parameter.Size = (int)dataRow["ColumnSize"];
			parameter.SourceColumn = (string)dataRow["ColumnName"];

			return parameter;
        }

		protected override IDbConnection GetConnection(string connectionString) {
			var connection = m_factory.CreateConnection();
			connection.ConnectionString = connectionString;
			return connection;
		}

		protected override string GetParameterDesignator(int count) {
			return "?p" + count;
		}

	}

#pragma warning restore
}
